﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using EnvRide.Core.ObjectModel;
using CodeMadeSimple.Common.Tests;
using CodeMadeSimple.Common.Validation;
using CodeMadeSimple.Common.Tests.Validation;
using System.Xml;
using CodeMadeSimple.PropertiesManagement;
using System.IO;

namespace EnvRide.Core.UnitTests
{
    [TestFixture]
    public class AttributeOverrideIncludeTests : OverrideIncludeTests<AttributeOverrideInclude>
    {
        private const string FILE_PATH = "AttributeOverrideIncludeTests.xml";

        [Test]
        public void Process()
        {
            EnvRide.Core.ObjectModel.Environment env = Helper.CreateDummyEnvironment();

            env.IncludedAttributeOverrides = new AttributeOverrideIncludeCollection();

            AttributeOverrideInclude attOverInc = new AttributeOverrideInclude();
            attOverInc.Environment = env;
            attOverInc.Project = env.Project;

            env.IncludedAttributeOverrides.Add(attOverInc);

            ExceptionAssert.AssertNullArgumentException("args", () => attOverInc.Process(null));

            XmlDocument doc = new XmlDocument();
            doc.Load(FILE_PATH);

            EnvRideProcessArguments args = new EnvRideProcessArguments { Document = doc };

            attOverInc.FilePath = "SubFolder\\FileToInclude.envRide";
            attOverInc.EnvironmentName = "EnvToInclude1";

            args.HasErrors = false;

            attOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root includedAtt5=\"includedValue5\" includedAtt6=\"includedValue6\" includedAtt3=\"includedValue3\" includedAtt4=\"includedValue4\" includedAtt1=\"includedValue1\" includedAtt2=\"includedValue2\" />", doc.OuterXml);

            doc.Load(FILE_PATH);

            attOverInc.OverrideName = "AttOver1";

            args.HasErrors = false;

            attOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root includedAtt1=\"includedValue1\" />", doc.OuterXml);

            doc.Load(FILE_PATH);

            attOverInc.OverrideName = "AttOver1,AttOver3";

            args.HasErrors = false;

            attOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root includedAtt1=\"includedValue1\" includedAtt3=\"includedValue3\" />", doc.OuterXml);

            attOverInc.OverrideName = "AttOver3,AttOver1,attOver5";

            args.HasErrors = false;

            doc.Load(FILE_PATH);

            attOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root includedAtt3=\"includedValue3\" includedAtt1=\"includedValue1\" includedAtt5=\"includedValue5\" />", doc.OuterXml);

            attOverInc.If = "false";

            args.HasErrors = false;

            doc.Load(FILE_PATH);

            attOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root />", doc.OuterXml);

            attOverInc.If = "true";

            attOverInc.EnvironmentName = "EnvWithProperty";
            attOverInc.OverrideName = "AttWithProp";

            args.HasErrors = false;

            Appender.Clear();

            doc.Load(FILE_PATH);

            attOverInc.Process(args);

            AssertHasErrors(args, new [] { GetPropertyContainerNullMessage() });

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root attWithProp=\"${Prop}\" />", doc.OuterXml);

            PropertyContext ctx = new PropertyContext("Ctx");
            ctx.AddProperty(new Property { Name = "Prop", Value = "PropValue" });
            ctx.AddProperty(new Property { Name = "CurrentFolder", Value = ".\\" });

            attOverInc.FilePath = "${CurrentFolder}\\" + attOverInc.FilePath;

            args.PropertyContainer = ctx;

            args.HasErrors = false;

            Appender.Clear();

            doc.Load(FILE_PATH);

            args.HasErrors = false;

            attOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root attWithProp=\"PropValue\" />", doc.OuterXml);

            PropertyContext relatedCtx = new PropertyContext("Related");
            relatedCtx.AddProperty(new Property { Name = "Prop", Value = "RelatedValue" });

            ctx.AddRelationship("Related", relatedCtx);
                        
            attOverInc.PropertiesPrefix = ">Related:";

            args.HasErrors = false;

            Appender.Clear();

            doc.Load(FILE_PATH);

            Assert.IsNull(args.PropertiesPrefix);

            attOverInc.Process(args);

            Assert.IsNull(args.PropertiesPrefix, ARGS_PROPS_PFX_RET_TO_PREV_VALUE_MSG);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root attWithProp=\"RelatedValue\" />", doc.OuterXml);

            ProcessWithErrors(FILE_PATH, attOverInc, doc, args);
        }

        [Test]
        public void Validate()
        {
            AttributeOverrideInclude attOverInc = new AttributeOverrideInclude();

            Validate(attOverInc);
        }

        
    }
}
